//
// Created by 相开原 on 2022/3/23.
//

#include "../headers/utility.h"

void background() {
    struct time_item now;
    int past = 0;
    while (1) {
        system_sleep(60);
        pointer *temp = NULL;
        get_timeItem(&now);
        if (now.hour == 20 && past == 19) { //每晚20点检查过期商品
            puts("20点到啦！正在检查临过期库存……");
            temp = overdue_check(3, head_fruitStored, temp);
            if (temp->next != NULL) puts("请及时前往清理库存！");
            pointer_free(temp);
            puts("正在检查临过期商品");
            temp = overdue_check(3, head_fruitStored, temp);
            if (temp->next != NULL) puts("请及时前往处理！");
            pointer_free(temp);
        }
        past = now.hour;
    }
}
//创建线程用于定时提醒过期信息
void setCheck() {
#if _WIN32
    _beginthread(background, 0, NULL);
#elif __linux__
//    linux下多线程暂时不支持（cmake配置文件中没有添加-lpthread）
//    pthread_t thread;
//    pthread_create(&thread, NULL, (void *) &background, NULL);
#elif __APPLE__
    pthread_t thread;
    pthread_create(&thread, NULL, (void *) &background, NULL);
#endif
}

//获取当前系统日期和时间
void get_timeItem(struct time_item *dt) {
    time_t t;
    struct tm *lt;
    time(&t);   //获取Unix时间戳。
    lt = localtime(&t); //转为时间结构。
    dt->year = lt->tm_year + 1900;
    dt->month = lt->tm_mon + 1;
    dt->day = lt->tm_mday;
    dt->hour = lt->tm_hour;
    dt->minute = lt->tm_min;
    dt->second = lt->tm_sec;
}

//传入两个date结构体，返回两个date结构体的差值（单位：天）
int get_dayPassed(struct time_item start, struct time_item end) {
    int y1, m1, d1;
    int y2, m2, d2;

    m1 = (start.month + 9) % 12;
    y1 = start.year - m1 / 10;
    d1 = 365 * y1 + y1 / 4 - y1 / 100 + y1 / 400 + (m1 * 306 + 5) / 10 + (start.day - 1);

    m2 = (end.month + 9) % 12;
    y2 = end.year - m2 / 10;
    d2 = 365 * y2 + y2 / 4 - y2 / 100 + y2 / 400 + (m2 * 306 + 5) / 10 + (end.day - 1);

    return d2 - d1;
}


//传入一个date结构体和一个天数，返回该天之后的日期
void get_dateAfter(struct time_item start, int day, struct time_item *end) {
    int mon[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

    if ((start.year % 4 == 0 && start.year % 100 != 0) || start.year % 400 == 0) {//判断闰年
        mon[2] = 29;
    } else
        mon[2] = 28;
    for (int i = 1; i <= day; i++) {
        start.day += 1;
        if (start.day > mon[start.month]) {
            start.day -= mon[start.month];
            start.month++;
            if (start.month > 12) {
                start.year++;
                start.month = 1;
                if ((start.year % 4 == 0 && start.year % 100 != 0) || start.year % 400 == 0) {//判断闰年
                    mon[2] = 29;
                } else
                    mon[2] = 28;
            }
        }
    }
    *end = start;
}

//将传入的数组（至少64位）转化为MD5
void get_MD5(char *password) {
    char MD5[64];
    MD5_get(password, MD5);
    strcpy(password, MD5);
}

//gets读取一行输入，转化为非负整数（若MIN==MAX则代表不考虑范围）
//当 MIN == MAX == 1 时，仍然考虑范围
bool input_int(int *container, int MIN, int MAX) {
    while (1) {
        fflush(stdin);
        char input[64];
        bool flag = true;
        fgets(input, 64, stdin);
        if (input[0] == '\n')
            return false;
        for (int i = 0; i < strlen(input); i++) {
            if (input[i] == '\n') {
                input[i] = '\0';
                break;
            }
            if (input[i] < '0' || input[i] > '9') {
                flag = false;
                break;
            }
        }
        if (flag) {
            if (MIN == MAX && MIN == 1 && atoi(input) == 1) {
                *container = 1;
                return true;
            } else {
                if (MIN == MAX && MIN != 1) {
                    *container = atoi(input);
                    return true;
                } else {
                    int temp = atoi(input);
                    if (temp >= MIN && temp <= MAX) {
                        *container = temp;
                        return true;
                    }
                }
            }
        }
        printf("⚠️您的输入有误，请重新输入：");
    }
}

//gets读取一行输入，转化为浮点数
bool input_double(double *container) {
    while (1) {
        fflush(stdin);
        char input[64];
        bool flag = true;
        fgets(input, 64, stdin);
        if (input[0] == '\n')
            return false;
        for (int i = 0; i < strlen(input); i++) {
            if (input[i] == '\n') {
                input[i] = '\0';
                break;
            }
            if (input[i] < '0' || input[i] > '9') {
                if (input[i] == '.')
                    continue;
                flag = false;
                break;
            }
        }
        if (flag) {
            *container = atof(input);
            if ((int)(*container * 1000) % 10 > 4)  //四舍五入
                *container += 0.1;
            return true;
        } else
            printf("⚠️您的输入有误，请重新输入：");
    }
}

//gets读取一个字符串，判断是否合法
bool input_string(char container[], int maxLine) {
    while (1) {
        fflush(stdin);
        char input[256];
        bool flag = true;
        fgets(input, 64, stdin);
        if (input[0] == '\n')
            return false;
        if (strlen(input) > maxLine)
            flag = false;
        for (int i = 0; i < strlen(input); i++) {
            if (input[i] == '\n') {
                input[i] = '\0';
                break;
            }
            if (input[i] == '\t' || input[i] == ' ') {
                flag = false;
                break;
            }
        }
        if (flag) {
            strcpy(container, input);
            return true;
        } else
            printf("⚠️ 您的输入有误，请重新输入：");
    }
}



//判断文件是否为空文件
bool isFileOK(char *path) {
    if (access(path, F_OK) == 0) {
        FILE *fp = fopen(path, "r");
        char temp[256];
        fgets(temp, 256, fp);   //读取一行
        char ch = fgetc(fp);
        if (ch != EOF) {
            fclose(fp);
            return true;
        }
        fclose(fp);
    }
    return false;
}

/* \033[字符的显示方式;字符的颜色;字符的背景颜色m 需要显示的字符 \033[m
 * 字符的显示方式:
 *      0（默认值）、1（加粗）、2（灰显）、3（斜体）、4（下划线）、7（反显）、9（删除线）
 * 字符的颜色:
 *      30（黑色）、31（红色）、32（绿色）、 33（黄色）、34（深蓝色）、35（紫色）、36（浅蓝色）、37（白色）
 * 字符的背景颜色:
 *      40（黑色）、41（红色）、42（绿色）、 43（黄色）、44（蓝色）、45（紫色）、46（浅蓝色）、47（白色）
*/
void terminal(char *str, int font, int color, int background) {
    if (background == -1)
        printf("\033[%d;%dm %s \033[m", font, color, str);
    else
        printf("\033[%d;%d;%dm %s \033[m", font, color, background, str);
}


//跨平台的清屏解决方案
void system_clear() {
#if _WIN32
    system("cls");
#elif __linux__
    system("clear");
#elif __APPLE__
    system("clear");
#endif
}

//跨平台的延时解决方案
void system_sleep(int second) {
#if _WIN32
    Sleep(second * 1000);
#elif __linux__
    sleep(second);
#elif __APPLE__
    sleep(second);
#endif
}

//跨平台的暂停解决方案（有bug）
void system_pause() {
#if _WIN32
    system("pause");
#elif __linux__
    system("read");
#elif __APPLE__
    system("read -n 1");
#endif
}

//跨平台的文件夹创建解决方案
int folder(char *path) {
#if _WIN32
    return mkdir(path);
#elif __linux__
    return mkdir(path, 0777);
#elif __APPLE__
    return mkdir(path, 0777);
#endif
}

//将文本转化为enum
int text_to_priceMode(char *text) {
    if (!strcmp(text, "retail") || !strcmp(text, "零售"))
        return 0;
    if (!strcmp(text, "promotion") || !strcmp(text, "促销"))
        return 1;
    if (!strcmp(text, "wholesale") || !strcmp(text, "批发"))
        return 2;
    if (!strcmp(text, "gift") || !strcmp(text, "赠送"))
        return 3;
    return -1;
}

//将enum转为文本
//retail, promotion, wholesale, gift
char *priceMode_to_text(int mode) {
    switch (mode) {
        case 0:
            return "零售";
        case 1:
            return "促销";
        case 2:
            return "批发";
        case 3:
            return "赠送";
        default:
            return "未知";
    }
}

//将文本转为enum
int text_to_fruitLevel(char *text) {
    if (!strcmp(text, "good") || !strcmp(text, "优"))
        return 0;
    if (!strcmp(text, "middle") || !strcmp(text, "中"))
        return 1;
    if (!strcmp(text, "bad") || !strcmp(text, "劣"))
        return 2;
    return -1;
}

//将enum转为文本
//good, middle, bad
char *fruitLevel_to_text(int mode) {
    switch (mode){
        case 0:
            return "优";
        case 1:
            return "中";
        case 2:
            return "劣";
        default:
            return "未知";
    }
}